#include "enemy.h"

enemy::enemy(){
	e_sprite = NULL;
	e_spriteAnim = NULL;

	e_maxSpeedX = 0.7;// was 1.0
	e_maxSpeedXOrgin = e_maxSpeedX;
	e_maxSpeedY = 7.0;
	e_walkingSpeed = 0.6;
	e_gravityConstant = 2.0;

	e_health=10;
	e_AI=1;
	e_facingRight = true;
	e_dead = false;
	e_onPatrol = false;
	chargeRecently=false;
	enemyChargeCounter=0;
	didShoot=false;
	shotTimer=0;

	e_position.x = 0.0;
	e_position.y = 0.0;
	e_localPosition.x = 0.0;
	e_localPosition.y = 0.0;
	e_enemyOffset.x = 0.0;
	e_enemyOffset.y = 0.0;
	e_velocity.x = 0.0;
	e_velocity.y = 0.0;

	e_boundingBox.top= e_position.y;
	e_boundingBox.bottom= e_position.y + 31.0;
	e_boundingBox.left= e_position.x;
	e_boundingBox.right= e_position.x + 31.0;
}

enemy::~enemy(){
	lnSpriteDestroy(e_sprite);
//	e_sprite = NULL;
//	e_spriteAnim = NULL;
}

void enemy::createEnemy(const void *sprData, const void *sprPalette){
	e_sprite = lnSpriteCreate(SCREEN_MAIN, SPRSIZE_32x32, COLMODE_16, sprData, sprPalette);
	e_spriteAnim = lnSpriteAnimBind(e_sprite, sprData, 1, 7);
}

void enemy::destoryEnemySprite(){
	lnSpriteDestroy(e_sprite);
}

void enemy::updateEnemy(int start,int end){
	applyGravity();
	//printf("charge counter %i\n",enemyChargeCounter);
	if(shotTimer >0){
		shotTimer--;
	}else{
		didShoot=false;
	}
	if(enemyChargeCounter >= 300){
		enemyChargeCounter--;
	}else if(enemyChargeCounter > 0){
		enemyChargeCounter--;
		e_maxSpeedX=e_maxSpeedXOrgin;
	}else{
		chargeRecently=false;
	}

	if(e_velocity.x > e_maxSpeedX){
		e_velocity.x = e_maxSpeedX;
	}else if(e_velocity.x < -e_maxSpeedX){
		e_velocity.x =-e_maxSpeedX;
	}
	if(e_velocity.y > e_maxSpeedY){
		e_velocity.y = e_maxSpeedY;
	}else if(e_velocity.y < -e_maxSpeedY){
		e_velocity.y =-e_maxSpeedY;
	}
	e_positionPrev.x = e_position.x;
	e_positionPrev.y = e_position.y;
	e_position.x += e_velocity.x;
	e_position.y += e_velocity.y;

	e_prevBoundingBox.top=e_positionPrev.y;
	e_prevBoundingBox.bottom=e_positionPrev.y +31.0;
	e_prevBoundingBox.left=e_positionPrev.x;
	e_prevBoundingBox.right=e_positionPrev.x +31.0;

	e_boundingBox.top=e_position.y;
	e_boundingBox.bottom=e_position.y +31.0;
	e_boundingBox.left=e_position.x;
	e_boundingBox.right=e_position.x +31.0;

	display();
	handleAnimation(start,end);
}

void enemy::display(){
	e_localPosition.x = e_position.x - e_enemyOffset.x;
	e_localPosition.y = e_position.y - e_enemyOffset.y;
	if(e_localPosition.x < -32.0 || e_localPosition.y < -32.0){
		e_sprite->isHidden=true;
	}else if(e_localPosition.x > (Fixed)SCREEN_WIDTH || e_localPosition.y > (Fixed)SCREEN_HEIGHT){
		e_sprite->isHidden=true;
	}else{
		e_sprite->isHidden=false;
	}
		e_sprite->posX = (int)e_localPosition.x;
		e_sprite->posY = (int)e_localPosition.y;
}

void enemy::move(int direction){
	if (direction == 1) {
	   //move right
	   e_velocity.x += e_walkingSpeed;
	  e_facingRight = false;
	} else if (direction == 0) {
	   //move left
	   e_velocity.x -= e_walkingSpeed;
	   e_facingRight = true;
	}else if(direction == 3){
		//stop
		e_velocity.x = 0;
	}else if(direction == 4){
		//move up
		e_velocity.y -= e_walkingSpeed;
	}else if(direction == 5){
		//move down
		e_velocity.y += e_walkingSpeed;
	}
}

void enemy::applyGravity(){
	e_velocity.y += e_gravityConstant;
}

void enemy::applyDamage(int damage){
	e_health -= damage;
	if(e_health <= 0){
		e_dead = true;
	}
}

void enemy::setPosition(tFloat posX,tFloat posY){
	e_position.x = posX;
	e_position.y = posY;
	e_patrolPos.x = posX;
	e_patrolPos.y = posY;
	display();
}

void enemy::handleAnimation(int start,int end){
	if(e_AI==1){
		e_spriteAnim->animStart = 0;
		e_spriteAnim->animEnd= 6;
		lnSpriteAnimLoop(e_sprite,ANIMTYPE_LOOP,0,1);
	}else if(e_AI==2){
		e_spriteAnim->animStart = 0;
		e_spriteAnim->animEnd= 0;
		lnSpriteAnimLoop(e_sprite,ANIMTYPE_LOOP,0,1);
	}else if(e_AI==3){
		e_spriteAnim->animStart = 0;
		e_spriteAnim->animEnd= 0;
		lnSpriteAnimLoop(e_sprite,ANIMTYPE_LOOP,0,1);
	}else if(e_AI==4){
		e_spriteAnim->animStart = 0;
		e_spriteAnim->animEnd = 4;
		lnSpriteAnimLoop(e_sprite,ANIMTYPE_LOOP,0,1);
	}

	if(e_facingRight){
		e_sprite->hFlip=true;
	}else{
		e_sprite->hFlip=false;
	}

}

void enemy::setOffset(tFloat posX,tFloat posY){
	e_enemyOffset.x = posX;
	e_enemyOffset.y = posY;
}

void enemy::setHealth(int health){
	e_health=health;
}

void enemy::setHidden(bool hidden){
	if(hidden){
		e_sprite->isHidden=true;
	}else{
		e_sprite->isHidden=false;
	}
}
void enemy::printInfo(){
	//consoleClear();
	printf("Enemy X-Cordinate: %03.2f\n",(float)e_position.x);
	printf("Enemy Y-Cordinate: %03.2f\n",(float)e_position.y);
	printf("Enemy X-offset:  %02.2f\n",(float)e_enemyOffset.x);
	printf("Enemy Y-offset:  %02.2f\n",(float)e_enemyOffset.y);
}

BoundingBox enemy::getBounds(){
	return e_boundingBox;
}

bool enemy::checkCollide(BoundingBox target){
	if(e_boundingBox.left > target.right || target.left > e_boundingBox.right){
		return false;  //No collision
	}
	if(e_boundingBox.top > target.bottom || target.top > e_boundingBox.bottom){
		return false;  //No collision
	}
	return true;  //Collision
}
bool enemy::checkCollideXprev(BoundingBox target){
	if(e_prevBoundingBox.left > target.right ||
		e_prevBoundingBox.right < target.left){
			return false;
	}
	return true;
}

bool enemy::checkCollideYprev(BoundingBox target){
	if(e_prevBoundingBox.top >= target.bottom ||
		e_prevBoundingBox.bottom <= target.top){
			return false;
	}
	return true;
}

bool enemy::isDead(){
	return e_dead;
}

void enemy::setAI(int AI){
	e_AI = AI;
	if((e_AI > 1) && (e_AI !=4)){
		e_gravityConstant=0.0;
	}
}

int enemy::getAI(){
	return e_AI;
}

void enemy::enemyproximity(tFloat posX,tFloat posY){
	float distanceX = 100.0;
	float distanceY = 64.0;
	if(e_AI==1){
		if(((posX-e_position.x) > -distanceX) && ((posX-e_position.x) < distanceX)){
			if(((posY-e_position.y) > -distanceY) && ((posY-e_position.y) < distanceY)){
				enemyAI(posX,posY);
			}
		}else{
			move(3);//stay still
		}
	}else{
		enemyAI(posX,posY);
	}
}

void enemy::enemyAI(tFloat posX,tFloat posY){
	if(e_AI == 0){
	}else if(e_AI == 1){
		if(!chargeRecently && ((posX - e_position.x < 32.0) || (posX - e_position.x > -32.0))){
			chargeRecently=true;
			enemyChargeCounter=30+5*60;
			e_maxSpeedX = 2.0;
		}
		if(posX < e_position.x && (e_position.x-posX > 0.1)){
			move(0);//move left
		}else if(posX > e_position.x && (posX-e_position.x > 0.1)){
			move(1);//move right
		}else {
			e_velocity.x = 0.0;
		}
	}else if(e_AI == 2){
		e_gravityConstant=0.0;
		tFloat patrolPointRight = e_patrolPos.x + 64.0;
		tFloat patrolPointLeft = e_patrolPos.x - 64.0;
		if((e_position.y-posY) > -96.0){
			if(((e_position.x -posX) < 8.0) && ((e_position.x-posX) > -8.0)){
				if(!didShoot){
					didShoot=true;
					shotTimer=5*60;
				weapon *temp = new weapon();
				temp->createWeaponSprite(enemy2Tiles,enemy2Pal,32,1,4,6,20);
				temp->setHidden(false);
				temp->setDamage(10);
				temp->markedForDeletion=false;
				temp->setOffset(e_enemyOffset.x,e_enemyOffset.y);
				temp->setPos(e_position.x,e_position.y+32.0);
				temp->move(2);
				game* Game = game::getInstance();
				Game->projectiles.push_back(temp);
				}
			}
		}
		if((e_position.x == e_patrolPos.x) && (e_onPatrol == false)){
			move(0);
			e_onPatrol=true;
		}else if(e_position.x > patrolPointRight){
			move(0);
			move(0);
		}else if(e_position.x < patrolPointLeft){
			move(1);
			move(1);
		}
	}else if(e_AI == 3){
		e_gravityConstant=0.0;
		tFloat patrolPointUp = e_patrolPos.y - 64.0;
		tFloat patrolPointDown = e_patrolPos.y + 64.0;
		if(((e_position.x -posX) < 128.0) && ((e_position.x-posX) > -128.0)){
			if(((e_position.y -posY) < 8.0) && ((e_position.y-posY) > -8.0)){
				if(!didShoot){
				didShoot=true;
				shotTimer=5*60;
				weapon *temp = new weapon();
				temp->createWeaponSprite(enemy3Tiles,enemy3Pal,32,1,4,12,10);
				temp->setHidden(false);
				temp->setDamage(10);
				temp->markedForDeletion=false;
				temp->setOffset(e_enemyOffset.x,e_enemyOffset.y);
				//printf("%f %f\n",(float)e_position.x,(float)e_position.y);
				if(posX > e_position.x){
					temp->setPos(e_position.x+32.0,e_position.y);
					temp->move(1);
				}else{
					temp->setPos(e_position.x-32.0,e_position.y);
					temp->move(0);
				}	
				game* Game = game::getInstance();
				Game->projectiles.push_back(temp);
				}
			}
		}
		if((e_position.y == e_patrolPos.y) && (e_onPatrol == false)){
			move(4);
		}else if(e_position.y > patrolPointDown){
			move(4);//move up
			move(4);
		}else if(e_position.y < patrolPointUp){
			move(5);//move down
			move(5);
		}
	}else if(e_AI == 4){
		//AKS
		//hardcoded boss fight
		//consoleClear();
		if(rand()%2 == 0){
			if(!chargeRecently && ((posX - e_position.x < 32.0) || (posX - e_position.x > -32.0))){
				chargeRecently=true;
				enemyChargeCounter=30+5*60;
				e_maxSpeedX = 2.0;
			}
			if(posX < e_position.x && (e_position.x-posX > 0.1)){
				move(0);//move left
			}else if(posX > e_position.x && (posX-e_position.x > 0.1)){
				move(1);//move right
			}else {
				e_velocity.x = 0.0;
			}
		}else{
			if(((e_position.x -posX) < 128.0) && ((e_position.x-posX) > -128.0)){
				if(((e_position.y -posY) < 8.0) && ((e_position.y-posY) > -8.0)){
					if(!didShoot){
					didShoot=true;
					shotTimer=5*60;
					weapon *temp = new weapon();
					temp->createWeaponSprite(BossTiles,BossPal,32,8,8,10,12);
					temp->setHidden(false);
					temp->setDamage(10);
					temp->markedForDeletion=false;
					temp->setOffset(e_enemyOffset.x,e_enemyOffset.y);
					if(posX > e_position.x){
						temp->setPos(e_position.x,e_position.y);
						temp->move(1);
					}else{
						temp->setPos(e_position.x-32.0,e_position.y);
						temp->move(0);
					}	
					game* Game = game::getInstance();
					Game->projectiles.push_back(temp);
					}
				}
			}
		}
	}
}

bool enemy::getFacingRight(){
	return e_facingRight;
}

t2DVector enemy::getPos(){
	return e_position;
}

void enemy::stopVertical(){
	e_velocity.y=0.0;
	e_inAir=false;
}

void enemy::stopHorizontal(){
	e_velocity.x=0.0;
}

t2DVector enemy::getPosPrev(){
	return e_positionPrev;
}